package com.bsoft.advance.core.codec;

import com.bsoft.advance.core.serialization.SerializationFactory;
import com.bsoft.advance.core.protocol.MessageHeader;
import com.bsoft.advance.core.protocol.MessageProtocol;
import com.bsoft.advance.core.serialization.Serialization;
import com.bsoft.advance.core.serialization.SerializationType;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;

import java.nio.charset.Charset;

/**
 * rpc自定义编码器
 */
public class RpcEncoder<T> extends MessageToByteEncoder<MessageProtocol<T>> {

    /**
     * +---------------------------------------------------------------+
     * | 魔数 2byte | 协议版本号 1byte | 序列化算法 1byte | 报文类型 1byte  |
     * +---------------------------------------------------------------+
     * | 状态 1byte |        消息Id 32byte     |      数据长度 4byte     |
     * +---------------------------------------------------------------+
     * |                   数据内容 （长度不定）                          |
     * +---------------------------------------------------------------+
     */
    @Override
    protected void encode(ChannelHandlerContext channelHandlerContext, MessageProtocol<T> protocol, ByteBuf byteBuf) throws Exception {
        MessageHeader header = protocol.getHeader();
        // 魔数（short = 2byte）
        byteBuf.writeShort(header.getMagic());

        // 协议版本号
        byteBuf.writeByte(header.getVersion());

        // 序列化算法
        byteBuf.writeByte(header.getSerialization());

        // 报文类型
        byteBuf.writeByte(header.getMsgType());

        // 状态
        byteBuf.writeByte(header.getStatus());

        // 消息 ID（自定义字符串）
        byteBuf.writeCharSequence(header.getRequestId(), Charset.forName("UTF-8"));

        // 根据请求头中的序列化方式序列化数据内容
        Serialization serialization = SerializationFactory.getSerialization(SerializationType.parseByType(header.getSerialization()));
        byte[] data = serialization.serialize(protocol.getBody());

        // 数据长度
        byteBuf.writeInt(data.length);

        // 数据内容
        byteBuf.writeBytes(data);
    }
}
